package com.caration.shell.action;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.caration.shell.R;

public class SwipeyTabs extends ViewGroup implements OnPageChangeListener {
	private IndicatorAdapter mIndicatorAdapter;
	private int mCurrentIndex;
	private int mBarHeight;
	private int mIndicatorHeight;
	private int mActivatedColor;
	private int mDefaultColor;
	private int mMiddleBasePosition[];
	private int mRightBasePosition[];
	private int mLeftBasePosition[];
	private int mTargetPosition[];
	private Paint mPaint;
	private int mLastWidthMeasure;

	public SwipeyTabs(Context context) {
		this(context, null);
	}

	public SwipeyTabs(Context context, AttributeSet attributeset) {
		this(context, attributeset, 0);
	}

	public SwipeyTabs(Context context, AttributeSet attributeset, int defStyle) {
		super(context, attributeset, defStyle);
		mCurrentIndex = -1;
		mDefaultColor = 0xff949494;
		mLastWidthMeasure = -1;
		TypedArray typedarray = context.obtainStyledAttributes(attributeset,
				R.styleable.swipey, defStyle, 0);
		mActivatedColor = typedarray.getColor(
				R.styleable.swipey_bottomBarColor, 0xff96aa39);
		mBarHeight = typedarray.getDimensionPixelSize(
				R.styleable.swipey_bottomBarHeight, 2);
		mIndicatorHeight = typedarray.getDimensionPixelSize(
				R.styleable.swipey_tabIndicatorHeight, 3);
		typedarray.recycle();
		setHorizontalFadingEdgeEnabled(true);
		setFadingEdgeLength((int) (0.5F + 35F * getResources()
				.getDisplayMetrics().density));
		setWillNotDraw(false);
		mPaint = new Paint();
		mPaint.setColor(mActivatedColor);
	}

	private void calcOffset(int index, int[] offsets) {
		if (mIndicatorAdapter == null)
			return;
		int count = mIndicatorAdapter.getCount();
		if ((index < 0) || (index >= count))
			return;
		while (count < offsets.length) {
			offsets[count] = -1;
			count++;
			continue;
		}
		TextView textView = null;
		int width = getMeasuredWidth();
		View v = getChildAt(index);
		offsets[index] = (width / 2 - v.getMeasuredWidth() / 2);
		for (int j = index - 1; j >= 0; j--) {
			textView = (TextView) getChildAt(j);
			if (j != index - 1)
				offsets[j] = (0 - textView.getMeasuredWidth() - width);
			else
				offsets[j] = (0 - textView.getPaddingLeft());
			offsets[j] = Math.min(offsets[j],
					offsets[(j + 1)] - textView.getMeasuredWidth());
		}
		for (int i = index + 1; i < count; i++) {
			textView = (TextView) getChildAt(i);
			if (i != index + 1)
				offsets[i] = (width * 2);
			else
				offsets[i] = (width - textView.getMeasuredWidth() + textView
						.getPaddingRight());
			textView = (TextView) getChildAt(i - 1);
			offsets[i] = Math.max(offsets[i],
					offsets[(i - 1)] + textView.getMeasuredWidth());
		}
	}

	private void setupTabView(boolean fix) {
		if (mIndicatorAdapter != null) {
			calcOffset(mCurrentIndex, mMiddleBasePosition);
			calcOffset(1 + mCurrentIndex, mRightBasePosition);
			calcOffset(-1 + mCurrentIndex, mLeftBasePosition);
			int count = mIndicatorAdapter.getCount();
			for (int i = 0; i < count; i++) {
				TextView textView = (TextView) getChildAt(i);
				if (i < mCurrentIndex) {
					textView.setEllipsize(null);
					textView.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
				} else if (i == mCurrentIndex) {
					textView.setEllipsize(TextUtils.TruncateAt.END);
					textView.setGravity(Gravity.CENTER);
				} else {
					textView.setEllipsize(null);
					textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
				}
			}
			if (fix) {
				for (int j = 0; j < count; j++) {
					mTargetPosition[j] = mMiddleBasePosition[j];
				}
			}
		}
	}

	public final void setAdapter(IndicatorAdapter adapter) {
		mIndicatorAdapter = adapter;
		mCurrentIndex = -1;
		mMiddleBasePosition = null;
		mRightBasePosition = null;
		mLeftBasePosition = null;
		mTargetPosition = null;
		removeAllViews();
		if (mIndicatorAdapter != null) {
			int count = mIndicatorAdapter.getCount();
			for (int i = 0; i < count; i++)
				addView(mIndicatorAdapter.getTabView(i, this));
			mCurrentIndex = 0;
			mMiddleBasePosition = new int[count];
			mRightBasePosition = new int[count];
			mLeftBasePosition = new int[count];
			mTargetPosition = new int[count];
			mLastWidthMeasure = -1;
			requestLayout();
		}
	}

	protected void dispatchDraw(Canvas canvas) {
		if (mCurrentIndex != -1) {
			View view = getChildAt(mCurrentIndex);
			int left = mTargetPosition[mCurrentIndex];
			int top = getHeight() - getPaddingBottom() - mBarHeight
					- mIndicatorHeight;
			int viewCenter = (left + view.getMeasuredWidth())
					- view.getMeasuredWidth() / 2;
			float center = getWidth() / 2f;
			float ratio = 1F - Math.min(
					Math.abs((viewCenter - center) / (center / 3)), 1.0F);
			// Logger.e("viewCenter:" + viewCenter + " top:" + top + " ratio:"
			// + ratio + " left:" + left + " right:"
			// + (left + view.getMeasuredWidth()));
			mPaint.setAlpha((int) (255F * ratio));
			canvas.drawRect(left, top, left + view.getMeasuredWidth(), top
					+ mIndicatorHeight, mPaint);
			int count = mIndicatorAdapter.getCount();
			for (int i = 0; i < count; i++) {
				TextView textview = (TextView) getChildAt(i);
				if (mCurrentIndex != i) {
					textview.setTextColor(mDefaultColor);
				} else {
					float colorRatio = 1F - ratio;
					float alpha = (float) Color.alpha(mActivatedColor) / 255F;
					float red = (float) Color.red(mActivatedColor) / 255F;
					float green = (float) Color.green(mActivatedColor) / 255F;
					float blue = (float) Color.blue(mActivatedColor) / 255F;
					float defAlpha = (float) Color.alpha(mDefaultColor) / 255F;
					float defRed = (float) Color.red(mDefaultColor) / 255F;
					float defGreen = (float) Color.green(mDefaultColor) / 255F;
					float defBlue = (float) Color.blue(mDefaultColor) / 255F;

					alpha += (defAlpha - alpha) * colorRatio;
					red += (defRed - red) * colorRatio;
					green += (defGreen - green) * colorRatio;
					blue += (defBlue - blue) * colorRatio;
					
					alpha = Math.max(Math.min(alpha, 1F), 0F);
					red = Math.max(Math.min(red, 1F), 0F);
					green = Math.max(Math.min(green, 1F), 0F);
					blue = Math.max(Math.min(blue, 1F), 0F);
					
					textview.setTextColor(Color.argb((int) (alpha * 255F),
							(int) (red * 255F), (int) (green * 255F),
							(int) (blue * 255F)));
				}
			}
		}
		super.dispatchDraw(canvas);
	}

	public void draw(Canvas canvas) {
		super.draw(canvas);
		int top = getHeight() - getPaddingBottom() - mBarHeight;
		mPaint.setAlpha(255);
		canvas.drawRect(0f, top, getWidth(), top + mBarHeight, mPaint);
	}

	protected float getLeftFadingEdgeStrength() {
		return 1F;
	}

	protected float getRightFadingEdgeStrength() {
		return 1F;
	}

	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		if (mIndicatorAdapter != null) {
			int count = mIndicatorAdapter.getCount();
			for (int i = 0; i < count; i++) {
				View localView = getChildAt(i);
				localView.layout(mTargetPosition[i], getPaddingTop(),
						mTargetPosition[i] + localView.getMeasuredWidth(),
						getPaddingTop() + localView.getMeasuredHeight());
			}
		}
	}

	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int heightMeasure = -1;
		int widthMeasure = MeasureSpec.getSize(widthMeasureSpec);
		if (mIndicatorAdapter != null) {
			int count = mIndicatorAdapter.getCount();
			for (int i = 0; i < count; i++) {
				LayoutParams layoutparams = getChildAt(i).getLayoutParams();
				int width = MeasureSpec.makeMeasureSpec(
						(int) (0.6f * widthMeasure), MeasureSpec.AT_MOST);
				int height = MeasureSpec.makeMeasureSpec(layoutparams.height,
						MeasureSpec.EXACTLY);
				getChildAt(i).measure(width, height);
			}
		}
		View view = getChildAt(0);
		if (view != null) {
			heightMeasure = view.getMeasuredHeight();
		}
		setMeasuredDimension(
				resolveSize(
						widthMeasure + getPaddingLeft() + getPaddingRight(),
						widthMeasureSpec),
				resolveSize(heightMeasure + mBarHeight + getPaddingTop()
						+ getPaddingBottom(), heightMeasureSpec));
		if (mLastWidthMeasure != widthMeasure) {
			mLastWidthMeasure = widthMeasure;
			setupTabView(true);
		}
	}

	@Override
	public void onPageScrolled(int position, float positionOffset,
			int positionOffsetPixels) {
		// Logger.e("position:" + position + " posOffset:" + positionOffset
		// + " posOffsetPx" + positionOffsetPixels);
		if (mIndicatorAdapter != null) {
			int count = mIndicatorAdapter.getCount();
			byte direction;
			if (positionOffsetPixels == 0 || mCurrentIndex != position) {
				if (positionOffsetPixels == 0 || mCurrentIndex == position) {
					positionOffset = 0F;
					direction = 0;
				} else {
					direction = 1;
					positionOffset = 1F - positionOffset;
				}
			} else {
				direction = -1;
			}
			for (int i = 0; i < count; i++) {
				float middlePosition = mMiddleBasePosition[i];
				int srcPosition = 0;
				switch (direction) {
				case 0:
					srcPosition = mMiddleBasePosition[i];
					break;
				case 1:
					srcPosition = mLeftBasePosition[i];
					break;
				case -1:
					srcPosition = mRightBasePosition[i];
					break;
				}
				mTargetPosition[i] = (int) (middlePosition + 0.5F + positionOffset
						* (srcPosition - middlePosition));
			}

			requestLayout();
			invalidate();
		}
	}

	@Override
	public void onPageSelected(int position) {
		mCurrentIndex = position;
		setupTabView(false);
	}

	@Override
	public void onPageScrollStateChanged(int state) {

	}
}
